using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;

namespace Janus.NorthwindDemo2007
{
	public abstract class ApplicationFolder
	{

		protected FolderLoadMode mLoadMode = FolderLoadMode.CurrentFolder;

		protected string mFolderName;
        protected string mFolderDescription;        
        protected string mEditImageKey="EditItem";
        protected string mNewImageKey = "NewItem";
		protected FolderFeatures mSupportedFeatures;

		private ApplicationFolderCollection mFolders;
		private FolderViewCollection mViews;
		private FolderView mCurrentView;
		private ContentViewControl mContentViewControl;
		private DataControl mPreviewControl;
		private string mImageKey;
		private DataProvider mDataProvider;
		private Janus.Windows.UI.Dock.UIPanelBase mNavigatorPanel;
		private ApplicationFolder mParentFolder;

	#region protected methods

		//Derived classes can override this method to fill the FolderViews
		//collection as needed. By default, this method loads the views from the
		//controls used by the folder or from the settings stored in the settings file.
		protected virtual void LoadFolderViews()
		{
			bool viewsLoaded = false;
			if (NorthwindApp.ReadSettingsFromDS)
			{
				DataRow[] views = null;
				views = NorthwindApp.ConfigDataSet.FolderViews.Select("ParentFolder = '" + this.GetType().FullName + "'");

				if (views.Length > 0)
				{
					foreach (ConfigDataSet.FolderViewsRow row in views)
					{
						FolderView newView = new FolderView(row.ViewName, (ContentViewType)row.ContentViewType, row.LayoutName);
						newView.ReadingPaneLocation = (ReadingPaneLocation)row.ReadingPaneLocation;
						mViews.Add(newView);
					}
					viewsLoaded = true;
				}
			}
			if (! viewsLoaded)
			{
				//load all possible views and load the settings from the
				//layouts defined at design time
				LoadViewsFromControl(ContentViewType.DashBoard);
				LoadViewsFromControl(ContentViewType.GridView);
				LoadViewsFromControl(ContentViewType.ScheduleView);
				LoadViewsFromControl(ContentViewType.TimelineView);
			}
		}

		//Derived classes must override this method and return the type
		//of the Control used to preview data in the main form if they support
		//ReadingPane
		protected virtual Type GetPreviewControlType
		{
			get
			{
				return null;
			}
		}
        
		//Derived classes must override this method and return the type
		//of the ContentViewControl used to present its data in the main form
		protected virtual Type GetTypeOfView(ContentViewType viewType)
		{
			return null;
		}

		//Derived classes must override this method to create the
		//appropriate data provider
		protected virtual DataProvider CreateDataProvider()
		{
			return null;
		}
		protected ContentViewControl CreateContentViewControl(ContentViewType viewType)
		{
			Type controlType = this.GetTypeOfView(viewType);
			if (controlType != null)
			{
				ContentViewControl ctl = null;
				ctl = (ContentViewControl)(Activator.CreateInstance(controlType));
				ctl.LoadSettings();
				return ctl;
			}
			else
			{
				return null;
			}
		}
		protected virtual void CreateContentViewControl()
		{
			if (CurrentView != null)
			{
				this.mContentViewControl = this.CreateContentViewControl(this.CurrentView.ContentViewType);
				mContentViewControl.LoadSettings();
				if (this.DataProvider != null)
				{
					mContentViewControl.DataProvider = this.DataProvider;
				}
			}
		}

		protected virtual void ReleaseContentView()
		{
			if (mContentViewControl != null)
			{
				if (mContentViewControl.Parent != null)
				{
					//Dispose the control only if it is free
					//if the control has a parent, just release the reference and
					//let its parent form dispose it.
					mContentViewControl.Dispose();
				}
				mContentViewControl = null;
			}
		}
		protected void AddChildFolder(ApplicationFolder folder)
		{
			this.Folders.Add(folder);
			folder.mParentFolder = this;
		}
	#endregion

	#region Private Methods
		private void LoadViewsFromControl(ContentViewType viewType)
		{
			ContentViewControl viewControl = this.CreateContentViewControl(viewType);
			if (viewControl != null)
			{
				//get an array with defined views
				FolderView[] gridViewFolders = viewControl.GetDefinedViews();
				foreach (FolderView fView in gridViewFolders)
				{
					if (this.Supports(FolderFeatures.ReadingPane))
					{
						fView.ReadingPaneLocation = ReadingPaneLocation.Bottom;
					}
					else
					{
						fView.ReadingPaneLocation = ReadingPaneLocation.Off;
					}
					mViews.Add(fView);
				}
				viewControl.Dispose();
			}
		}
	#endregion

	#region Public Properties
		public string FolderName
		{
			get
			{
				return mFolderName;
			}
			set
			{
				mFolderName = value;
			}
		}
        public string FolderDescription
        {
            get { return mFolderDescription; }
            set { mFolderDescription = value; }
        }
        public string EditImageKey
        {
            get
            {
                return mEditImageKey;
            }
            set
            {
                mEditImageKey = value;
            }
        }
        public string NewImageKey
        {
            get
            {
                return mNewImageKey;
            }
            set
            {
                mNewImageKey = value;
            }
        }
		//Inheritors are responsible of filling the Folder collection
		//when they are initialized.
		public ApplicationFolderCollection Folders
		{
			get
			{
				if ((mFolders == null))
				{
					mFolders = new ApplicationFolderCollection();
				}
				return mFolders;
			}
		}

		//Inheritors are responsible of filling the Views collection
		//when they are initialized.
		public FolderViewCollection Views
		{
			get
			{
				if ((mViews == null))
				{
					mViews = new FolderViewCollection();
					LoadFolderViews();
				}
				return mViews;
			}
		}
      

		public virtual Janus.NorthwindDemo2007.DataControl PreviewControl
		{
			get
			{
				if (mPreviewControl == null)
				{
					Type controlType = this.GetPreviewControlType;
					if (controlType != null)
					{
						mPreviewControl = (DataControl)(Activator.CreateInstance(controlType));
					}
					else
					{
						if (this.Supports(FolderFeatures.ReadingPane))
						{
							throw new NotImplementedException(this.GetType().FullName + " must implement GetPreviewControlType method if ReadingPane is supported.");
						}
					}
				}
				return mPreviewControl;
			}
		}

		public virtual void ReleasePreviewControl()
		{
			if (mPreviewControl != null)
			{
				if ((mPreviewControl.Parent == null))
				{
					mPreviewControl.Dispose();
				}
				mPreviewControl = null;
			}
		}

		public FolderView CurrentView
		{
			get
			{
				if (mCurrentView == null)
				{
					this.CurrentView = this.DefaultView;
				}
				return mCurrentView;
			}
			set
			{
				if (value != null && ! mViews.Contains(value))
				{
					throw new ArgumentException("View is not defined for the folder.");
				}
				if (mCurrentView != value)
				{
					if (mContentViewControl != null)
					{
						if (mContentViewControl.GetType() != GetTypeOfView(value.ContentViewType))
						{
							//release content view only if the type of the content view
							//is of a different type than the one already loaded
							ReleaseContentView();
						}
					}
					mCurrentView = value;
				}
			}
		}

		public string ImageKey
		{
			get
			{
				return mImageKey;
			}
			set
			{
				mImageKey = value;
			}
		}

		public bool Supports(FolderFeatures feature)
		{
			return ((mSupportedFeatures & feature) == feature);
		}

		public FolderLoadMode LoadMode
		{
			get
			{
				return mLoadMode;
			}
		}
		//Derived classes must override this method if they support NewItem
		public virtual void AddNew()
		{
			MessageBox.Show("Not Implemented");
		}
        public virtual bool CanAdd
        {
            get
            {
                return false;
            }
        }
		//Derived classes can override this property if default view is not
		//the first view in the collection
		protected virtual FolderView DefaultView
		{
			get
			{
				if (Views.Count > 0)
				{
					return mViews[0];
				}
				else
				{
					return null;
				}
			}
		}

		public ContentViewControl CurrentContentView
		{
			get
			{
				if ((this.mContentViewControl == null))
				{
					CreateContentViewControl();
				}
				return mContentViewControl;
			}
		}

		public DataProvider DataProvider
		{
			get
			{
				return mDataProvider;
			}
		}
		public virtual void Load()
		{
			if (mDataProvider == null)
			{
				mDataProvider = CreateDataProvider();
			}
			if (mDataProvider != null)
			{
				mDataProvider.Fill();
			}
			if (this.mContentViewControl == null)
			{
				this.CreateContentViewControl();
			}
			//If Not (Me.CurrentContentView Is Nothing) Then
			//    Me.CurrentContentView.DataProvider = mDataProvider
			//End If
		}
		public bool UpdateData()
		{
			if (this.CurrentContentView != null)
			{
				if (! this.CurrentContentView.UpdateChanges())
				{
					return true;
				}
			}
			if (mDataProvider != null)
			{
				return mDataProvider.Update();
			}
			else
			{
				return true;
			}
		}
		public virtual void Unload()
		{
			if (this.LoadMode != FolderLoadMode.Always)
			{
				if (mContentViewControl != null)
				{
					this.ReleaseContentView();
				}
				if (mDataProvider != null)
				{
					mDataProvider.Dispose();
					mDataProvider = null;
				}

			}

		}


		public ApplicationFolder Find(string folderName)
		{
			if (string.Compare(this.FolderName, folderName, true) == 0)
			{
				return this;
			}

			ApplicationFolder folderFound = null;
			foreach (ApplicationFolder folder in this.Folders)
			{
				folderFound = folder.Find(folderName);
				if (folderFound != null)
				{
					return folderFound;
				}
			}
			return null;
		}

		public void SaveViewSettings(Janus.NorthwindDemo2007.ConfigDataSet.FolderViewsDataTable table)
		{
			if (mViews != null)
			{
				ConfigDataSet.FolderViewsRow row = null;

				foreach (FolderView view in this.mViews)
				{
					row = (ConfigDataSet.FolderViewsRow)table.Rows.Find(new object[] {view.ViewName, this.GetType().FullName});
					if (row == null)
					{
						row = table.AddFolderViewsRow(view.ViewName, this.GetType().FullName, System.Convert.ToInt32(view.ContentViewType), System.Convert.ToInt32(view.ReadingPaneLocation), view.LayoutName);
					}
					else
					{
						row.BeginEdit();
						row.ContentViewType = System.Convert.ToInt32(view.ContentViewType);
						row.LayoutName = view.LayoutName;
						row.ParentFolder = this.GetType().FullName;
						row.ReadingPaneLocation = System.Convert.ToInt32(view.ReadingPaneLocation);
						row.ViewName = view.ViewName;
						row.EndEdit();
					}
				}
			}
			if (mFolders != null)
			{
				foreach (ApplicationFolder childFolder in this.mFolders)
				{
					childFolder.SaveViewSettings(table);
				}
			}
		}

		public Janus.Windows.UI.Dock.UIPanelBase NavigatorPanel
		{
			get
			{
				if (mNavigatorPanel == null)
				{
					//return the navigator panel of the parent
					if (mParentFolder == null)
					{
						return null;
					}
					else
					{
						return mParentFolder.NavigatorPanel;
					}
				}
				else
				{
					return mNavigatorPanel;
				}
			}
			set
			{
				this.mNavigatorPanel = value;
			}
		}
		public ApplicationFolder ParenFolder
		{
			get
			{
				return mParentFolder;
			}
		}
	#endregion

	}

	[Flags()]
	public enum FolderFeatures: int
	{
		None = 0,
		MultipleViews = 1,
		ReadingPane = 2,
		NewItem = 4,
		All = 7
	}

	public enum ContentViewType: int
	{
		DashBoard,
		GridView,
		ScheduleView,
		TimelineView
	}

	public enum FolderLoadMode: int
	{
		Never,
		CurrentFolder,
		Always
	}
} //end of root namespace